Research
Security News
Kill Switch Hidden in npm Packages Typosquatting Chalk and Chokidar
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
mixinable
is a small functional utility library allowing you to use mixins in your code. More specifically, it allows you to create mixin containers that apply mixin method application strategies to mixin method implementations.
Mixins are usually classes that can easily be shared, modified and extended using standard language features. mixinable
supports asynchronous methods returning Promises
.
Using NPM:
npm install -S mixinable
Using Yarn:
yarn add mixinable
To be able to use mixinable
, you will have to make sure your environment supports Promise
: if, for example, you need to support IE11, you will have to polyfill Promise
.
define(definition, mixins)
The main export of mixinable
is a define()
function accepting a mixin container definition and an array of mixins, i.e. classes. The definition hash is made up of strategy
functions prescribing how to handle different mixin methods you provide. It returns a create()
function that accepts whatever arguments your mixins' constructor()
s accept.
import define from 'mixinable';
const create = define(
{
// mixin strategy function
bar(functions, arg) {
return functions.pop()(arg);
},
},
[
// mixin implementation
class {
bar(arg) {
console.log(arg);
},
}
]
);
const foo = create();
foo.bar('yeah!');
// yeah!
Speaking of which: mixinable
creates a separate hidden mixin instance for every mixin you provide. When used inside a mixin method, this
refers to this hidden instance.
Mixin methods not included in your definition are only accessible from within the mixin instance itself, but not from the outside.
import define from 'mixinable';
const create = define(
{
bar(functions, arg) {
return functions.pop()(arg);
},
},
[
// mixin implementations
class {
// public mixin method
bar(arg) {
this.qux(arg);
},
// private mixin method
qux(arg) {
console.log(arg);
},
}
]
);
const foo = create();
foo.bar('yeah!');
// yeah!
console.log(typeof foo.bar, typeof foo.qux);
// function undefined
Mixin definitions can be (or contain) custom constructors. These functions are being passed the create()
function's arguments upon creation.
import define from 'mixinable';
const create = define({}, [
// mixin contructors
class {
constructor(arg) {
console.log(arg);
}
},
]);
create('yee-hah!');
// yee-hah!
define.override
override
is a helper implementating a mixin strategy that resembles classical inherintance (class ... extends
): it simply calls the last method implementation.
import define, { override } from 'mixinable';
const create = define({
// mixin strategy function
bar: override,
}, [
// mixin implementations
class {
bar() {
console.log(1);
}
},
class {
bar() {
console.log(2);
}
},
]);
const foo = create();
foo.bar();
// 2
override
returns a Promise
if one of its implementations does. If you want it to always return a Promise
, i.e. if you can not be sure whether one of your implementations might return one, please use define.async.override
.
override
is aliased to callable
in all places, enabling implementers to communicate their intentions more clearly: override
is often used to provide callable (utility) methods.
define.parallel
parallel
is a helper implementating a mixin strategy that executes all defined implementations in parallel. This is probably most useful if asynchronous implementations are involved.
import define, { parallel } from 'mixinable';
const create = define({
// mixin strategy function
bar: parallel,
}, [
// mixin implementations
class {
bar(val, inc) {
return val + inc;
}
},
class {
bar(val, inc) {
return val + inc;
}
},
]);
const foo = create();
foo.bar(0, 1).then(res => console.log(res));
// [1, 1]
parallel
returns a Promise
if one of its implementations does. If you want it to always return a Promise
, i.e. if you can not be sure whether one of your implementations might return one, please use define.async.parallel
.
If you want to make sure parallel
never returns a Promise
, please use it as define.sync.parallel
- or, better yet, use it as define.sync.sequence
, for that is technically correct.
define.pipe
pipe
is a helper implementating a strategy that passes each implementation's output to the next, using the first argument as the initial value. All other arguments are being passed to all implementations as-is.
import define, { pipe } from 'mixinable';
const create = define({
// mixin strategy function
bar: pipe,
}, [
// mixin implementations
class {
bar(val, inc) {
return val + inc;
}
},
class {
bar(val, inc) {
return val + inc;
}
},
]);
const foo = create();
foo.bar(0, 1).then(res => console.log(res));
// 2
pipe
returns a Promise
if one of its implementations does. If you want it to always return a Promise
, i.e. if you can not be sure whether one of your implementations might return one, please use define.async.pipe
.
define.compose
compose
works essentially identically as pipe
, but in reverse order: the very last implementation receives the initial value and the first implementation returns the final output.
import define, { compose } from 'mixinable';
const mixin = define({
// mixin strategy function
bar: compose,
}, [
// mixin implementations
// ...
]);
compose
returns a Promise
if one of its implementations does. If you want it to always return a Promise
, i.e. if you can not be sure whether one of your implementations might return one, please use define.async.compose
.
You can supply your own mixin strategies: such strategies are plain functions that receive the defined implementations as their first argument. The following example shows a naïve re-implementation of the override
strategy.
import define from 'mixinable';
const mixin = define({
// mixin strategy function
bar(functions, ...args) {
functions.pop().apply(null, args);
},
}, [
// mixin implementation
class {
bar(arg) {
console.log(arg);
},
},
]);
const foo = create();
foo.bar(1);
// 1
define.async
All of the strategies described above return a Promise
if one of their implementations does. If you want them to always return a Promise
please use define.async.{override/callable,parallel,pipe,compose}
.
define.sync
If you want to make sure one of the strategies never returns a Promise
please use define.sync.{override/callable,parallel/sequence,pipe,compose}
. If you do, an Error
will be thrown if a Promise
is returned.
If you want to contribute to this project, create a fork of its repository using the GitHub UI. Check out your new fork to your computer:
mkdir mixinable && cd $_
git clone git@github.com:user/mixinable.git
Afterwards, you can yarn install
the required dev dependencies and start hacking away. When you are finished, please do go ahead and create a pull request.
mixinable
itself is (almost) entirely written in ECMAScript 5 and adheres to semistandard code style. Please make sure your contribution does, too.
FAQs
Functional JavaScript Mixin Utility
The npm package mixinable receives a total of 152 weekly downloads. As such, mixinable popularity was classified as not popular.
We found that mixinable demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.